﻿package com.dusk.net
{
	import com.dusk.game.Logger;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	/**
	 * 全部加载完成后调度事件
	 */
	[Event(name = AssetLoader.ALL_LOAD_COMPLETE,type = "flash.events.Event")]
	
	/**
	 * 加载失败调度事件
	 */
	[Event(name = AssetLoader.LOAD_FAILED,type = "flash.events.Event")]
	
	/**
	 * 进度更新调度事件
	 * 在TreadVO中会将loader的LoadingInfo作为参数传递给回调函数
	 */
	[Event(name = AssetLoader.UPDATE_PROGRESS,type = "flash.events.Event")]
	
	public class AssetLoader extends EventDispatcher
	{
		
		private static const CURRENT_LOAD_COMPLETE:String = "currentFileComplete";
		
		public static const ALL_LOAD_COMPLETE:String = "allFilesComplete";
		
		public static const LOAD_FAILED:String = "loadFailed";
		
		public static const UPDATE_PROGRESS:String = "updateProgress";
		
		public static function getIns():AssetLoader
		{
			return new AssetLoader();
		}
		
		public function AssetLoader()
		{
			super();
			_urlLoader = new URLLoader();
			_urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			_urlLoader.addEventListener(Event.COMPLETE, loadCompleteHandler);
			_urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrHandler);
			_urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrHandler);
			_urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
		}
		
		public var isAuto:Boolean = true;
		
		private var _urlLoader:URLLoader;
		private var _queueLen:int = 0;
		private var _curByteLoaded:uint = 0;
		private var _curByteTotal:uint = 0;
		private var _assetQueue:Array = [];
		private var _isLoading:Boolean = false;
		
		public function get loadingInfo():Object
		{
			return {
				curNum:    _queueLen - _assetQueue.length,
				totalNum:  _queueLen,
				curPercent:Math.round(100 * _curByteLoaded / _curByteTotal)};
		}
		
		public function addItem(item:AssetItem):void
		{
			_assetQueue.push(item);
			_queueLen++;
			if(!isAuto) return;
			startLoad();
		}
		
		public function startLoad():void
		{
			if(_isLoading) return;
			_loadNext();
		}
		
		private function _loadNext():void
		{
			if(_assetQueue.length == 0)
			{
				_queueLen = 0;
				_isLoading = false;
				dispatchEvent(new Event(AssetLoader.ALL_LOAD_COMPLETE));
				return;
			}
			_isLoading = true;
			execute(_assetQueue[0]);
		}
		
		public function execute(item:AssetItem):void
		{
			if(item.bytes)
			{
				item.buildAsset();
				return;
			}
			Logger.log("LoadAsset: " + item.url);
			_urlLoader.load(new URLRequest(item.url));
		}
		
		private function loadCompleteHandler(evt:Event):void
		{
			_urlLoader.close();
			var item:AssetItem = _assetQueue[0] as AssetItem;
			item.bytes = _urlLoader.data as ByteArray;
			item.buildAsset(buildAssetComplete);
		}
		
		private function buildAssetComplete():void
		{
			_assetQueue.shift();
			dispatchEvent(new Event(CURRENT_LOAD_COMPLETE));
			_loadNext();
		}
		
		private function progressHandler(evt:ProgressEvent):void
		{
			_curByteLoaded = evt.bytesLoaded;
			_curByteTotal = evt.bytesTotal;
			dispatchEvent(new Event(UPDATE_PROGRESS));
		}
		
		private function ioErrHandler(evt:IOErrorEvent):void
		{
			dispatchEvent(new Event(LOAD_FAILED));
			Logger.logError(evt.text,this);
		}
		
		private function securityErrHandler(evt:SecurityErrorEvent):void
		{
			dispatchEvent(new Event(LOAD_FAILED));
			Logger.logError(evt.text,this);
		}
		
		public function destroy():void
		{
			_queueLen = 0;
			_curByteLoaded = 0;
			_curByteTotal = 0;
			_assetQueue.length = 0;
			_urlLoader = null;
		}
	}
}
